package fu.dan.qi.gen.processor;

import com.palantir.javapoet.*;
import fu.dan.qi.gen.annotation.*;

import javax.annotation.processing.*;
import javax.lang.model.*;
import javax.lang.model.element.*;
import javax.tools.*;
import java.io.*;
import java.util.*;
import java.util.stream.*;


@SupportedSourceVersion(SourceVersion.RELEASE_17)
public class PropertiesConstGenerator extends AbstractProcessor {


    @Override
    public Set<String> getSupportedAnnotationTypes() {
        Set<String> set = new HashSet<>();
        set.add(PropertiesConstant.class.getName());
        return set;
    }

    @Override
    public synchronized void init(ProcessingEnvironment processingEnv) {
        super.init(processingEnv);
    }

    @Override
    public boolean process(Set<? extends TypeElement> annotations,
                           RoundEnvironment roundEnv) {
        annotations.forEach(annotation -> {

            Set<? extends Element> elements = roundEnv.getElementsAnnotatedWith(
                    PropertiesConstant.class);
            elements.forEach(element -> {
                TypeElement typeElement = (TypeElement) element;
                try {
                    PropertiesConstant propertiesConstant = typeElement.getAnnotation(PropertiesConstant.class);
                    String packageName = propertiesConstant.packageName();
                    handlerElementPropertiesAnnotation(roundEnv, typeElement, packageName);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            });
        });
        return false;
    }

    private void handlerElementPropertiesAnnotation(RoundEnvironment roundEnv,
                                                    TypeElement element,
                                                    String packageName) throws IOException {
        String resultPackageName;
        if (packageName == null || packageName.isEmpty()) {
            PackageElement packageElement = (PackageElement) element.getEnclosingElement();
            resultPackageName = packageElement.getQualifiedName().toString();
        } else {
            resultPackageName = packageName;
        }
        Set<String> keys = getPropertiesKeys();
        JavaFileObject fileObject = super.processingEnv.getFiler().createSourceFile(
                resultPackageName + ".HelloWorld");
        PrintWriter printWriter = new PrintWriter(fileObject.openOutputStream());
        MethodSpec main = MethodSpec.methodBuilder("main")
                                    .addModifiers(Modifier.PUBLIC, Modifier.STATIC)
                                    .returns(void.class)
                                    .addParameter(String[].class, "args")
                                    .addStatement("$T.out.println($S)", System.class, "Hello, JavaPoet!")
                                    .build();

        TypeSpec helloWorld = TypeSpec.classBuilder("HelloWorld")
                                      .addModifiers(Modifier.PUBLIC, Modifier.FINAL)
                                      .addMethod(main)
                                      .build();

        JavaFile javaFile = JavaFile.builder(resultPackageName, helloWorld)
                                    .build();

        String string = javaFile.toString();
        printWriter.print(string);
        printWriter.close();
    }

    private Set<String> getPropertiesKeys() {
        Properties properties = new Properties();
        try {
            properties.load(this.getClass().getClassLoader().getResourceAsStream("application.properties"));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return properties.keySet().stream().map(Object::toString).collect(Collectors.toSet());
    }
}
